/**
 * Parse the time to string
 * @param {(Object|string|number)} time 时间
 * @param {string} cFormat 格式化选项 默认{y}-{m}-{d} {h}:{i}:{s}
 * @returns {string | null} 如果时间格式不正确，则返回null
 */
export function parseTime(time, cFormat) {
  if (arguments.length === 0 || !time) {
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if ((typeof time === 'string')) {
      if ((/^[0-9]+$/.test(time))) {
        // support "1548221490638"
        time = parseInt(time)
      } else {
        // support safari
        // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
        time = time.replace(new RegExp(/-/gm), '/')
      }
    }

    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
    const value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
    return value.toString().padStart(2, '0')
  })
  return time_str
}



/**
 * 校验身份证号码
 * @param {string} idCard 身份证号码
 * @returns {boolean} 是否有效 如果有效返回true，否则返回false 如果身份证号码格式不正确，则抛出错误
 */
export function isIdCard(idCard) {
  // 身份证号码应为18位  
  if (idCard.length !== 18) {
    throw new Error('身份证号码必须是18位');
  }
  // 身份证号码只能包含数字，最后一位可以是X或x  
  if (!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}([0-9Xx])$/.test(idCard)) {
    throw new Error('身份证号码格式不正确');
  }

  // 加权因子数组  
  const weightFactors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
  // 校验码对应值  
  const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];

  let sum = 0;
  for (let i = 0; i < idCard.length - 1; i++) {
    sum += parseInt(idCard[i]) * weightFactors[i];
  }

  const remainder = sum % 11;
  const expectedCheckCode = checkCodes[remainder];

  // 校验最后一位  
  if (expectedCheckCode !== idCard[17].toUpperCase()) {
    throw new Error('身份证号码校验码错误');
  }
  return true; // 如果所有检查都通过，则返回true  
}

/**
 * 解析身份证号码
 * @param {string} idCard 身份证号码
 * @returns {Object} 包含性别、年龄、出生日期的对象
 */
export function parseIDCard(idCard) {
  // 正则表达式匹配身份证号格式
  console.log('23:29:03 🚀 ~ file: index.js:230 ~ ', idCard)
  var reg = /^\d{17}[\dXx]$/;

  if (reg.test(idCard)) {
    // 提取出生日期
    var birthday = idCard.substring(6, 14);
    var year = birthday.substring(0, 4);
    var month = birthday.substring(4, 6);
    var day = birthday.substring(6, 8);

    // 计算年龄
    var currentYear = new Date().getFullYear();
    var age = currentYear - parseInt(year);
    // 提取性别
    var genderCode = parseInt(idCard.charAt(16));
    var gender = genderCode % 2 === 0 ? 0 : 1;  // 0 女 1 男
    console.log('23:44:11 🚀 ~ file: index.js:246 ~ ', age.length)
    return {
      birthday: year + "-" + month + "-" + day,
      age: age,
      gender: gender
    };
  }

  return null; // 身份证号格式不正确
}

/**
 * 格式化时间
 * @param {number} time 时间戳
 * @param {string} option 格式化选项 默认{d}天{h}小时{m}分钟{s}秒
 * @returns {string}
 */
export function formatTime(time, option) {
  if (('' + time).length === 10) {
    time = parseInt(time) * 1000
  } else {
    time = +time
  }
  const d = new Date(time)
  const now = Date.now()

  const diff = (now - d) / 1000

  if (diff < 30) {
    return '刚刚'
  } else if (diff < 3600) {
    // scss 1 hour
    return Math.ceil(diff / 60) + '分钟前'
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小时前'
  } else if (diff < 3600 * 24 * 2) {
    return '1天前'
  }
  if (option) {
    return parseTime(time, option)
  } else {
    return (
      d.getMonth() +
      1 +
      '月' +
      d.getDate() +
      '日' +
      d.getHours() +
      '时' +
      d.getMinutes() +
      '分'
    )
  }
}

/**
 * 时间差
 * @param {number} startTime 开始时间
 * @param {number} endTime 结束时间
 * @param {string} format 格式化选项 默认{d}天{h}小时{m}分钟{s}秒
 * @returns {string}
 */
export function timeDifference(startTime, endTime, format = '{d}天{h}小时{m}分钟{s}秒') {
  const startDate = startTime;  //开始时间
  const endTimeDate = endTime;  //结束时间
  const differenceDate = endTimeDate - startDate //时间差的毫秒数

  //计算出相差天数
  const days = Math.floor(differenceDate / (24 * 3600 * 1000))

  //计算出小时数
  const leave1 = differenceDate % (24 * 3600 * 1000)    //计算天数后剩余的毫秒数
  const hours = Math.floor(leave1 / (3600 * 1000))

  //计算相差分钟数
  const leave2 = leave1 % (3600 * 1000)        //计算小时数后剩余的毫秒数
  const minutes = Math.floor(leave2 / (60 * 1000))

  //计算相差秒数
  const leave3 = leave2 % (60 * 1000)      //计算分钟数后剩余的毫秒数
  const seconds = Math.round(leave3 / 1000)

  let result = format

  let parts = []
  
  if(days > 0) {
    parts.push(`${days}天`)
  }
  
  if(hours > 0) {
    parts.push(`${hours}小时`) 
  }
  
  if(minutes > 0) {
    parts.push(`${minutes}分钟`)
  }
  
  if(seconds > 0) {
    parts.push(`${seconds}秒`)
  }

  return parts.join('')
}



/**
 * 深拷贝
 * @param {Object} initalObj 初始对象
 * @returns {Object} 深拷贝后的对象
 */
export const deepClone = (initalObj) => {
  const obj = {};
  if(typeof initalObj !== 'object'){
    return initalObj
  }
  for (const key in initalObj) {
    if (typeof initalObj[key] === 'object') {
      //对数组特殊处理
      if (Array.isArray(initalObj[key])) {
        //用map方法返回新数组，将数组中的元素递归
        obj[key] = initalObj[key].map(item => deepClone(item))
      } else {
        //递归返回新的对象
        obj[key] = deepClone(initalObj[key]);
      }
    } else if (typeof initalObj[key] === 'function') {
      //返回新函数
      obj[key] = initalObj[key].bind(obj);
    } else {
      //基本类型直接返回
      obj[key] = initalObj[key];
    }
  }
  return obj;
}

/**
 * 手机号打码处理
 * @param {string} phone 手机号
 * @returns {string} 打码后的手机号
 */
export function maskPhone(phone) {
  if (!phone) return ''
  return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}

/**
 * 身份证号打码处理
 * @param {string} identity 身份证号
 * @returns {string} 打码后的身份证号
 */
export function maskIdentity(identity) {
  if (!identity) return ''
  return identity.replace(/(\d{6})\d{6}(\d{4})/, '$1******$2')
}